﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Threading;

namespace YahooMoviesStormer
{
    class YahooClient
    {
        public delegate void LoginPerformedHandler(YahooClient client, bool successful);
        public event LoginPerformedHandler LoginPerformed;

        public delegate void VotePerformedHandler(YahooClient client, bool successful);
        public event VotePerformedHandler VotePerformed;

        public delegate void AlreadVotedHandler(YahooClient client);
        public event AlreadVotedHandler AlreadVoted;

        Communications communications = new Communications();
        BackgroundWorker worker = new BackgroundWorker();
        public VoteInformation voteInformation;

        public YahooClient()
        {
            worker.DoWork += worker_DoWork;
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (Login())
                Vote();
        }

        public class VoteInformation
        {
            public string ReviewURL { get; set; }
            public string Username { get; set; }
            public string Password { get; set; }
            public bool DownVote { get; set; }
            public Communications.ProxyInfo Proxy { get; set; }
        }

        public void PerformVote(VoteInformation voteInformation, bool block = false)
        {
            this.voteInformation = voteInformation;
            communications.proxyInfo = voteInformation.Proxy;
            worker.RunWorkerAsync();
            if (block) while (worker.IsBusy) Thread.Sleep(200);
        }

        bool Login()
        {
            bool successful = false;
            try
            {
                communications.ClearCookies();

                string loginUrl = "https://login.yahoo.com/config/login?";
                string loginWebPage = communications.PerformGet(loginUrl);
                var dotU = Regex.Match(loginWebPage, "<input type=\"hidden\" name=\".u\" value=\"([^<]+)\">").Groups[1].Value;
                string dotChallenge = Regex.Match(loginWebPage, "<input type=\"hidden\" name=\".challenge\" value=\"([^<]+)\">").Groups[1].Value;
                
                var postData = new Communications.PostData();
                postData.AddValue(".tries", "1");
                postData.AddValue(".src", "");
                postData.AddValue(".md5", "");
                postData.AddValue(".hash", "");
                postData.AddValue(".js", "");
                postData.AddValue(".last", "");
                postData.AddValue("promo", "");
                postData.AddValue(".intl", "us");
                postData.AddValue(".bypass", "");
                postData.AddValue(".partner", "");
                postData.AddValue(".u", dotU);
                postData.AddValue(".v", "0");
                postData.AddValue(".challenge", "");
                postData.AddValue(".yplus", "");
                postData.AddValue(".emailCode", "");
                postData.AddValue("pkg", "");
                postData.AddValue("stepid", "");
                postData.AddValue(".ev", "");
                postData.AddValue("hasMsgr", "0");
                postData.AddValue(".chkP", "Y");
                postData.AddValue(".done", "http://my.yahoo.com");
                postData.AddValue(".pd", "_ver=0&c=&ivt=&sg=");
                postData.AddValue("pad", "3");
                postData.AddValue("aad", "3");
                postData.AddValue("login", voteInformation.Username);
                postData.AddValue("passwd", voteInformation.Password);
                postData.AddValue(".persistent", "y");
                postData.AddValue(".save", "");
                postData.AddValue("passwd_raw", "");
                var result = communications.PerformPost(loginUrl, postData, referer: loginUrl, allowAutoRedirect: true);

                successful = result.Contains("my.yahoo.com") || result.Contains("member");
            }
            catch { }

            LoginPerformed(this, successful);
            return successful;
        }

        bool Vote()
        {
            bool successful = false;
            try
            {
                string hasVotedString = "You found this review helpful";
                string hasDownVotedString = "You found this review\n not helpful";
                string reviewUrl = voteInformation.ReviewURL;
                string movieID = Regex.Match(reviewUrl, "mid=([^<]+)&uid").Groups[1].Value;
                string reviewWebPage = communications.PerformGet(reviewUrl, referer: string.Format("http://movies.yahoo.com/mvc/drv?mid={0}&s=rc_d", movieID));

                if (reviewWebPage.Contains(hasVotedString) || reviewWebPage.Contains(hasDownVotedString))
                {
                    AlreadVoted(this);
                    return false;
                }
                string voteUrl = Regex.Match(reviewWebPage, "<TABLE WIDTH=79 BORDER=0 CELLPADDING=0 CELLSPACING=0>\n<TR>\n<TD>\n<A HREF=\"([^<]+)\"\nONMOUSEOVER").Groups[1].Value;

                if (voteInformation.DownVote)
                    voteUrl = voteUrl.Replace("vote=1", "vote=0");

                var result = communications.PerformGet(voteUrl, referer: reviewUrl, allowAutoRedirect: true);
                successful = result.Contains(hasVotedString) ||  result.Contains(hasDownVotedString);
            }
            catch { }

            VotePerformed(this, successful);
            return successful;
        }
    }
}
